package com.nxj.factory;

import com.nxj.annotation.Autowired;
import com.nxj.annotation.Component;
import com.nxj.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@Component
public class ProxyFactory {

    @Autowired
    private TransactionManager transactionManager;

    /*
    public void setTransactionManager(TransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }*/

    public Object jdkProxy(Object o) {
        return Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object r;
                try {
                    transactionManager.beginTransaction();
                    System.out.println("class.invoke");
                    System.out.println(method);
                    r = method.invoke(o, args);
                    System.out.println("class invoked");
                } catch (Exception e) {
                    transactionManager.roll();
                    throw e;
                }
                transactionManager.commit();
                return r;
            }
        });
    }

    public Object cgLibProxy(Object o) {
        return Enhancer.create(o.getClass(), (MethodInterceptor) (o1, method, objects, methodProxy) -> {
            Object r;
            try {
                transactionManager.beginTransaction();
                r = method.invoke(o1, objects);
            } catch (Exception e) {
                transactionManager.roll();
                throw e;
            }
            transactionManager.commit();
            return r;
        });
    }
}
